/**
 * ****************************************************************************
 * Project: RoboBridge
 * ----------------------------------------------------------------------------
 * -------------------------- [c]2012 - KrawallMann ---------------------------
 * ---------------------- http://www.krawallmann.de.tc/ -----------------------
 * ****************************************************************************
 * File: LANRemoteDevice.java Package:
 * tc.de.krawallmann.robobridge.communication.lan Version: 1.0 Author(s):
 * KrawallMann
 * ****************************************************************************
 * Description:
 * ****************************************************************************
 */
package tc.de.krawallmann.robobridge.communication.lan;

import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import tc.de.krawallmann.robobridge.communication.AbstractRemoteCommunicationDevice;
import tc.de.krawallmann.robobridge.communication.CommunicationDeviceType;
import tc.de.krawallmann.robobridge.util.Exceptions;

/**
 * The Class LANRemoteDevice represents a device available on the LAN.
 * 
 * @author KrawallMann
 * @version 1.0
 */
public class LANRemoteDevice extends AbstractRemoteCommunicationDevice {

	/** The address. */
	private transient final InetAddress address;

	/** The name. */
	private transient final String name;

	/** The port. */
	private transient final int port;

	/**
	 * Instantiates a new lAN remote device.
	 * 
	 * @param deviceIP
	 *            the device ip
	 * @param port
	 *            the port
	 * @throws UnknownHostException
	 *             the unknown host exception
	 */
	public LANRemoteDevice(final String deviceIP, final int port) throws UnknownHostException {
		super();
		if (deviceIP == null) {
			throw Exceptions.onNullPointer(this, "ip");
		}
		if (port <= 0) {
			throw new IllegalStateException("Port " + port + " must be greater than 0");
		}
		address = InetAddress.getByName(deviceIP);
		this.port = port;
		name = address.getHostName();
	}

	/**
	 * Instantiates a new lAN remote device.
	 * 
	 * @param deviceIP
	 *            the device ip
	 * @param port
	 *            the port
	 * @param name
	 *            the name
	 * @throws UnknownHostException
	 *             the unknown host exception
	 */
	public LANRemoteDevice(final String deviceIP, final int port, final String name)
			throws UnknownHostException {
		super();
		if (deviceIP == null) {
			throw Exceptions.onNullPointer(this, "ip");
		}
		if (port <= 0) {
			throw new IllegalStateException("Port " + port + " must be greater than 0");
		}
		address = InetAddress.getByName(deviceIP);
		this.port = port;
		this.name = name;
	}

	/**
	 * Instantiates a new lAN remote device.
	 */
	protected LANRemoteDevice() {
		super();
		address = null;
		port = 0;
		name = "NULL";
	}

	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		final LANRemoteDevice other = (LANRemoteDevice) obj;
		if (address == null) {
			if (other.address != null) {
				return false;
			}
		} else if (!address.equals(other.address)) {
			return false;
		}
		if (name == null) {
			if (other.name != null) {
				return false;
			}
		} else if (!name.equals(other.name)) {
			return false;
		}
		if (port != other.port) {
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * @see communication.CommunicationDevice#getAddress()
	 */
	@Override
	public String getAddress() {
		return address.getHostAddress();
	}

	/*
	 * (non-Javadoc)
	 * @see communication.CommunicationDevice#getDeviceType()
	 */
	@Override
	public CommunicationDeviceType getDeviceType() {
		return CommunicationDeviceType.LAN_DEVICE;
	}

	/*
	 * (non-Javadoc)
	 * @see communication.CommunicationDevice#getName()
	 */
	@Override
	public String getName() {
		return name;
	}

	/**
	 * Gets the port.
	 * 
	 * @return the port
	 */
	public int getPort() {
		return port;
	}

	@Override
	public int hashCode() {
		int result = 1;
		result = 31 * result + (address == null ? 0 : address.hashCode());
		result = 31 * result + (name == null ? 0 : name.hashCode());
		result = 31 * result + port;
		return result;
	}

	/**
	 * Checks if the device is reachable.
	 * 
	 * @return true, if the device is reachable
	 */
	public boolean isReachable() {
		try {
			final Socket socket = new Socket();
			socket.connect(new InetSocketAddress(address, port), 1000);
			socket.close();
		} catch (final ConnectException exc) {
			if (exc.toString().contains("Connection refused")) {
				return true;
			}
			return false;
		} catch (final UnknownHostException e) {
			return false;
		} catch (final IOException e) {
			return false;
		}
		return true;
	}
}
